/*
 * Copyright (c) 2007 jNetX.
 * http://www.jnetx.com
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * jNetX. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license
 * agreement you entered into with jNetX.
 *
 * $Id$
 */
package com.jnetx.javax.sip.header;

import com.jnetx.javax.sip.util.Parametrized;

import javax.sip.address.URI;
import javax.sip.header.AuthorizationHeader;
import javax.sip.header.Header;
import java.text.ParseException;

/**
 * The Authorization header is used when a user agent wishes to authenticate
 * itself with a server - usually, but not necessarily, after receiving an
 * UNAUTHORIZED Response - by including an AuthorizationHeader with the
 * Request. The AuthorizationHeader consists of credentials
 * containing the authentication information of the user agent for the
 * realm of the resource being requested.
 * <p/>
 * This header field, along with Proxy-Authorization, breaks the general
 * rules about multiple header field values.  Although not a comma-
 * separated list, this header field name may be present multiple times,
 * and MUST NOT be combined into a single header line.
 * <p/>
 * For Example:<br>
 * <code>Authorization: Digest username="Alice", realm="atlanta.com",<br>
 * nonce="84a4cc6f3082121f32b42a2187831a9e",<br>
 * response="7587245234b3434cc3412213e5f113a5432"</code>
 *
 * @author <a href="mailto:dparhonin@jnetx.ru">Dmitry Parhonin</a>
 * @version $Revision$
 */
public class AuthorizationHeaderImpl extends ParametrizedHeaderBase implements AuthorizationHeader {
    private static final AuthorizationHeaderParser parser = new AuthorizationHeaderParser();

    private String scheme;
    private URI uri;
//    private Integer nonceCount;

    protected HeaderParser getParser() {
        return parser;
    }

    public AuthorizationHeaderImpl() {
        super(AuthorizationHeader.NAME);
    }

    AuthorizationHeaderImpl(byte[] data, int start, int end) {
        super(AuthorizationHeader.NAME, data, start, end);
    }

    @Override
    protected Parametrized<Header> createParametrized() {
        return new Parametrized<Header>(this, Parametrized.QuotationType.DOUBLE);
    }

    public Object clone() {
        final AuthorizationHeaderImpl header = new AuthorizationHeaderImpl();
        header.cloneBase(this);
        if (parsed) {
            header.cloneParameters(this);
            header.scheme = this.scheme;
            header.uri = this.uri;
        }
        return header;
    }

    protected String getValueAsString() {
        return scheme;
    }

    @Override
    protected StringBuilder getParametersAsString(StringBuilder sb, char delimiter) {
        final String params = parametrized.getParametersAsString(',');
        sb.append(' ');
        if (params != null && !params.equals("")) {
            sb.append(' ').append(params);
            if (uri != null)
                sb.append(uri.toString());
        } else
            sb.append(uri.toString());
        return sb;
    }

    public void setScheme(String scheme) {
        parse();
        this.scheme = scheme;
        invalidateHeaderData();
    }

    public String getScheme() {
        parse();
        return scheme;
    }

    public void setRealm(String realm) throws ParseException {
        setParameter("realm", realm);
    }

    public String getRealm() {
        return getParameter("realm");
    }

    public void setUsername(String username) throws ParseException {
        setParameter("username", username);
    }

    public String getUsername() {
        return getParameter("username");
    }

    public void setNonce(String nonce) throws ParseException {
        setParameter("nonce", nonce);
    }

    public String getNonce() {
        return getParameter("nonce");
    }

    public void setURI(URI uri) {
        parse();
        this.uri = uri;
        invalidateHeaderData();
    }

    public URI getURI() {
        parse();
        return this.uri;
    }

    public void setResponse(String response) throws ParseException {
        setParameter("response", response);
    }

    public String getResponse() {
        return getParameter("response");
    }

    public void setAlgorithm(String algorithm) throws ParseException {
        setParameter("algorithm", algorithm);
    }

    public String getAlgorithm() {
        return getParameter("algorithm");
    }

    public void setCNonce(String cNonce) throws ParseException {
        setParameter("cnonce", cNonce);
    }

    public String getCNonce() {
        return getParameter("cnonce");
    }

    public void setOpaque(String opaque) throws ParseException {
        setParameter("opaque", opaque);
    }

    public String getOpaque() {
        return getParameter("opague");
    }

    public void setQop(String qop) throws ParseException {
        setParameter("qop", qop);
    }

    public String getQop() {
        return getParameter("qop");
    }

    public void setNonceCount(int nonceCount) throws ParseException {
        if (nonceCount == -1)
            removeParameter("nc");
        else
            setParameter("nc", Integer.toString(nonceCount), Parametrized.QuotationType.NONE);
    }

    public int getNonceCount() {
        final String nc = getParameter("nc");
        if (nc == null)
            return -1;
        else
            return Integer.parseInt(nc);
    }

//    @Override
//    protected String getParametersAsString(char delimiter) {
//        final StringBuilder sb = new StringBuilder();
//        final String params = super.getParametersAsString(delimiter);
//        String lmt = "";
//        if (params != null && !params.equals("")) {
//            sb.append(params);
//            lmt = "" + delimiter;
//        }
//        if (uri != null) {
//            sb.append(lmt).append(uri.toString());
//            lmt = "" + delimiter;
//        }
//        if (nonceCount != null) {
//            sb.append(lmt).append(nonceCount.intValue());
//        }
//        return sb.toString();
//    }
}
